<template>
  <div class="locationMap" v-show="visible">
    <div class="dmap">
      <div id="map" />
      <div class="viewPosition">
        <div class="header">是否保存当前视点配置?</div>
        <div class="form">
          <button
            class="cancel"
            @click="close">取消</button>
          <button
            class="confirm"
            @click="confirm">确定</button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick} from 'vue'
import {Viewer, UrlTemplateImageryProvider, SceneMode, defined, Cartesian3, Cartographic,  Math as CesiumMath} from 'cesium';

const visible = ref(false);
const emit = defineEmits(['confirm']);
const areaId = ref(undefined);
const viewpointStr = ref(undefined);
let map;
/**
 * 初始化地图
 */
const initMap = () => {
  map = new Viewer('map',{
    useDefaultRenderLoop: true, // 是否自动渲染
    geocoder: false, // 地理位置查询定位控件
    homeButton: false, // 默认相机位置控件
    timeline: false, // 时间滚动条控件
    navigationHelpButton: false, // 默认的相机控制提示控件
    fullscreenButton: false, // 全屏控件
    sceneMode: SceneMode.COLUMBUS_VIEW, //场景模型 COLUMBUS_VIEW 2.5D
    scene3DOnly: false, // 每个几何实例仅以3D渲染以节省GPU内存
    baseLayerPicker: false, // 底图切换控件
    animation: false, // 控制场景动画的播放速度控件
    selectionIndicator: false, // 取消双击追踪实体行为
    requestRenderMode: false, // 如果为 true，则仅在场景中的变化所确定的需要时才会渲染帧。
    // maximumRenderTimeChange: Infinity, // 如果requestRenderMode为true，这个值定义了在请求渲染之前允许的模拟时间的最大变化。
    sceneModePicker: false, // 不创建SceneModePicker小部件。
    infoBox: false, // 不创建 InfoBox 小部件。
    navigationInstructionsInitiallyVisible: false, // 如果导航说明最初应该是可见的，则为真，如果在用户明确单击按钮之前不应显示，则为假。
    imageryProvider: new UrlTemplateImageryProvider({
      url: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png',
      subdomains: ['a', 'b', 'c', 'd']
    }), // 初始化默认球皮
    shouldAnimate: false, // 用于开启时钟视图模型
    showRenderLoopErrors: false, // 是否显示错误弹框
    orderIndependentTranslucency: true // 如果为 true 且配置支持，则使用与顺序无关的半透明。
  });
  map._cesiumWidget._creditContainer.style.display = 'none';
  setViewpoint(viewpointStr.value);
}

/**
 * 关闭视点
 */
const close = () => {
  visible.value = false;
}

/**
 * 视点确认
 */
const confirm = () => {
  visible.value = false;
  emit('confirm', getViewPointStr())
}
/** 获取视点字符串 */
const getViewPointStr = () =>{
  let result;
  if(map) {
    const camera = map.camera;
    const {positionCartographic , pitch, roll, heading} = camera;
    const {longitude, latitude, height} = positionCartographic;
    const viewpoint = {
      lng:CesiumMath.toDegrees(longitude), 
      lat:CesiumMath.toDegrees(latitude), 
      height, 
      pitch: CesiumMath.toDegrees(pitch), 
      roll: CesiumMath.toDegrees(roll), 
      heading: CesiumMath.toDegrees(heading)
    };
    result = JSON.stringify(viewpoint)
  }
  return result;
}

onMounted(() => {
  initMap();
})

/** 显示地图 */
const show = (id, viewpoint) => {
  visible.value = true;
  viewpointStr.value = viewpoint;
  nextTick(()=>{
    if(map) setViewpoint(viewpoint);
  })
}

const setViewpoint = (viewpointStr) =>{
  if(defined(viewpointStr)) {
    const viewpoint = JSON.parse(viewpointStr);
    const {lng, lat, height, pitch, roll, heading} = viewpoint;
    const positionCartographic = new Cartographic(CesiumMath.toRadians(lng), CesiumMath.toRadians(lat), height);
    map.camera.flyTo({
      destination: Cartographic.toCartesian(positionCartographic),
      orientation:{
        pitch: CesiumMath.toRadians(pitch), 
        roll: CesiumMath.toRadians(roll), 
        heading: CesiumMath.toRadians(heading)
      }
    })
  }
}

defineExpose({
  show
})
</script>

<style scoped lang="less">
.locationMap {
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  z-index: 9999;
  width: 100%;
  height: 100%;
}
.dmap {
  width: 100%;
  height: 100%;
  #map {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    margin: 0;
    overflow: hidden;
    padding: 0;
    font-family: sans-serif;
  }
}
.viewPosition {
  width: 420px;
  height: 132px;
  right: 130px;
  position: absolute;
  top: 40px;
  background: #061631b6;
  border-radius: 0px;
  .header {
    width: 192px;
    height: 20px;
    font-size: 16px;
    font-family: "Microsoft YaHei UI";
    font-weight: 400;
    color: #ffffff;
    top: 20px;
    left: 114px;
    position: relative;
  }

  .form {
    position: relative;
    top: 58px;
    left: 54px;
    font-size: 14px;
    font-family: "Microsoft YaHei UI";
  }

  .cancel {
    width: 150px;
    height: 34px;
    background: #f2f2f2;
    border: 0px solid #e9e9e9;
    border-radius: 0px;
    margin-right: 9px;
    color: #222222;
  }

  .confirm {
    width: 150px;
    height: 34px;
    background: #2071f5;
    border: 0px solid #e9e9e9;
    margin-left: 9px;
    color: #ffffff;
  }
}
</style>
